/*
 * Copyright (c) 2020-2021, Bluetrum Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020/12/10     greedyhao    The first version
 */

/**
 * Notice!
 * All functions or data that are called during an interrupt need to be in RAM.
 * You can do it the way exception_isr() does.
 */

#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_soft_spi.h"

struct rt_spi_device * spi;

//void send_byte(unsigned char b)
//{
//    rt_spi_send(spi, &b, 1);
//}
//
//unsigned char recv_byte()
//{
//    unsigned char ret;
//    rt_spi_recv(spi, &ret, 1);
//    return ret;
//}

unsigned char mcp2515_recv(unsigned char addr)
{
    {
        struct rt_spi_message message = { 0 };
        unsigned char buf[2] = { 0x03, addr };
        message.send_buf = buf;
        message.length = 2;
        message.cs_take = 1;
        rt_spi_transfer_message(spi, &message);
    }

    {
        struct rt_spi_message message = { 0 };
        unsigned char buf;
        message.recv_buf = &buf;
        message.length = 1;
        message.cs_release = 1;
        rt_spi_transfer_message(spi, &message);

        return buf;
    }
//    unsigned char ret;
//    send_byte(0x03);
//    send_byte(addr);
//    ret = recv_byte();
//    return ret;
}

void mcp2515_send(unsigned char addr, unsigned char data)
{
    struct rt_spi_message message = { 0 };
    unsigned char buf[3] = { 0x02, addr, data };
    message.send_buf = buf;
    message.length = 3;
    message.cs_take = 1;
    message.cs_release = 1;
    rt_spi_transfer_message(spi, &message);

//    send_byte(0x02);
//    send_byte(addr);
//    send_byte(data);
}

void mcp2515_bit_modify(unsigned char addr, unsigned char mask, unsigned char data)
{
    struct rt_spi_message message = { 0 };
    unsigned char buf[4] = { 0x05, addr, mask, data };
    message.send_buf = buf;
    message.length = 4;
    message.cs_take = 1;
    message.cs_release = 1;
    rt_spi_transfer_message(spi, &message);

//    send_byte(0x05);
//    send_byte(addr);
//    send_byte(mask);
//    send_byte(data);
}

void mcp2515_reset()
{
    struct rt_spi_message message = { 0 };
    unsigned char buf[1] = { 0xc0 };
    message.send_buf = buf;
    message.length = 1;
    message.cs_take = 1;
    message.cs_release = 1;
    rt_spi_transfer_message(spi, &message);

    // send_byte(0xc0);
}

// https://www.cnblogs.com/yikoulinux/p/13706054.html
void mcp2515_initialize(void)
{
    mcp2515_reset(); //复位
    mcp2515_send(0x0f, 0x80); //CANCTRL寄存器－－进入配置模式 中文DATASHEET 58页
    // 可以设置的波特率 5K 10K 15K 20K 25K 40K 50K 80K 100K 125K 200K 400K 500K 667K 800K 1M
    // https://www.kvaser.com/support/calculators/bit-timing-calculator/
    mcp2515_send(0x2A, 0x00); //CNF1位定时配置寄器   中文DATASHEET 41-42页
    mcp2515_send(0x29, 0x88); //CNF2位定时配置寄器   中文DATASHEET 41-42页
    mcp2515_send(0x28, 0x03); //CNF3位定时配置寄器   中文DATASHEET 41-43页
    mcp2515_send(0x2B, 0x1f);     //CANINTE中断使能寄存器  中文DATASHEET 50 页
    mcp2515_send(0x60, 0x60);     //RXB0CTRL接收缓冲器0 控制寄存器 中文DATASHEET 27 页
    //write_byte_2515(0x70, 0x20);   //接收缓冲器1控制寄存器
    mcp2515_bit_modify(0x0C, 0x0f, 0x0f); //BFPCTRL_RXnBF 引脚控制寄存器和状态寄存器 中文DATASHEET 29 页
    // mcp2515_send(0x0f, 0x40);   //CAN控制寄存器－－回环模式,用于测试
    mcp2515_send(0x0f, 0x00);   //CAN控制寄存器－－正常模式
}

void mcp2515_send_req()
{
    struct rt_spi_message message = { 0 };
    unsigned char buf[1] = { 0x81 };
    message.send_buf = buf;
    message.length = 1;
    message.cs_take = 1;
    message.cs_release = 1;
    rt_spi_transfer_message(spi, &message);

//    send_byte(0x81);   //发送请求命令
}

struct can_frame
{
    unsigned char can_id[4];
    unsigned char len;
    unsigned char data[8];
    unsigned char rx_idx; // 接收缓冲器 idx
};

void can_send(struct can_frame * f)
{
    unsigned char i;
    mcp2515_send(0x30, 0x03); //设置为发送最高优先级
    mcp2515_send(0x31, f->can_id[0]); //发送缓冲器0标准标识符高位
    mcp2515_send(0x32, f->can_id[1]); //发送缓冲器0标准标识符低位
    mcp2515_send(0x33, f->can_id[2]); //发送缓冲器0扩展标识符高位
    mcp2515_send(0x34, f->can_id[3]); //发送缓冲器0扩展标识符低位
    mcp2515_send(0x35, f->len);  //发送缓冲器0数据长度码8字节
    for (i = 0; i < f->len; i++)
    {
        mcp2515_send(0x36 + i, f->data[i]); //向txb缓冲器中写入8个字节
//      printf("%x ",tx_buff[i]);
    }
    mcp2515_send_req();

}

// unsigned char rx_buff[14]
// 0x60 RXB0CTRL——接收缓冲器 0 控制寄存器 （地址：60h）
//      RXB1CTRL——接收缓冲器 1 控制寄存器 （地址：70h）
// 0x61 RXBnSIDH——接收缓冲器 n 标准标识符高位 （地址：61h， 71h）
// 0x62 RXBnSIDL——接收缓冲器 n 标准标识符低位 （地址：62h， 72h）
// 0x63 RXBnEID8——接收缓冲器 n 扩展标识符高位 （地址：63h， 73h）
// 0x64 RXBnEID0——接收缓冲器 n 扩展标识符低位 （地址：64h， 74h）
// 0x65 RXBnDLC——接收缓冲器 n 数据长度码 （地址：65h， 75h）
// 0x66 RXBnDM——接收缓冲器 n 数据字段字节 M
//  - 0x6d
// Return: 0, no data
//         1, ok
unsigned char can_recv(struct can_frame * f)
{
    unsigned char i, flag;
    flag = mcp2515_recv(0x2c); //CANINTF——中断标志寄存器
    rt_kprintf("[0x2c] flag: %x ", flag);

    unsigned char base;
    unsigned char mask;
    if (flag & 0x1)
    {
        // //接收缓冲器0满中断标志位
        base = 0x60;
        mask = 0x01;
        f->rx_idx = 0;
    }
    else if (flag & 0x2)
    {
        //接收缓冲器1满中断标志位
        base = 0x70;
        mask = 0x02;
        f->rx_idx = 1;
    }
    else
    {
        return 0;
    }

    for (i = 0; i < 4; i++)
    {
        f->can_id[i] = mcp2515_recv(base + 0x1 + i);
    }
    f->len = mcp2515_recv(base + 0x5);
    for (i = 0; i < f->len; i++)
    {
        f->data[i] = mcp2515_recv(base + 0x6 + i);
    }

    mcp2515_bit_modify(0x2c, mask, 0x00); // clear rx buf 0

    return 1;
}

/*
 #define __AB32_PORT(port)   GPIO##port
 #define __AB32_GET_PIN_A(PIN)  PIN
 #define __AB32_GET_PIN_B(PIN)  8 + PIN
 #define __AB32_GET_PIN_E(PIN)  13 + PIN
 #define __AB32_GET_PIN_F(PIN)  21 + PIN
 */

int main(void)
{
    uint8_t pin = rt_pin_get("PE.1");
    rt_pin_mode(pin, PIN_MODE_OUTPUT);
    rt_kprintf("Hello, world\n");

    rt_soft_spi_device_attach("spi0", "spi0.0", RT_NULL, 19);
    spi = (struct rt_spi_device *) rt_device_find("spi0.0");

    rt_kprintf("spi0.0: %x\n", spi);
    if (spi == RT_NULL)
    {
        rt_kprintf("Can't find device on '%s'", "spi0.0");
        return -1;
    }

    struct rt_spi_configuration cfg;
    cfg.data_width = 8;
    cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
    cfg.max_hz = 10 * 1000 * 1000;
    rt_err_t err = rt_spi_configure(spi, &cfg); //配置传输模式
    rt_kprintf("rt_spi_configure result: %d\n", err);

    mcp2515_initialize();

    struct can_frame f0 = { .can_id = { 0x01, 0x02, 0x00, 0x00 }, .len = 4, .data = { 0x08, 0x10, 0x12, 0x14 }, };
    // can_send(&f0);

    for (;;)
    {
        struct can_frame f1 = { 0 };
        unsigned char ok = can_recv(&f1);
        rt_kprintf("recv1 ok: %d", ok);
        if (ok)
        {
            rt_kprintf(" can_id: %02x %02x data:", f1.can_id[0], f1.can_id[1]);
            for (int i = 0; i < f1.len; i++)
                rt_kprintf(" %02x", f1.data[i]);
        }
        else
        {
            rt_thread_mdelay(1);
        }
        rt_kprintf("\n");
    }

    while (1)
    {
        rt_pin_write(pin, PIN_LOW);
        rt_thread_mdelay(500);
        rt_pin_write(pin, PIN_HIGH);
        rt_thread_mdelay(500);
    }
}
